package com.harry.decoupling.impl.proxy;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import org.springframework.stereotype.Repository;

import com.harry.basis.BaseGeneric;
import com.harry.basis.BasePoEntity;
import com.harry.decoupling.defi.module.GenericDao;
import com.harry.decoupling.defi.proxy.GenericDaoProxy;
import com.harry.utility.query.InnerCriteria;
import com.harry.utility.query.PageCount;

@Repository
public class GenericProxyImplDao implements GenericDaoProxy {

	@Override
	public <T extends BasePoEntity> T expandEntityById(Class<T> entityClass, String id) throws Exception {
		return impl(entityClass).expandEntityById(id);
	}

	@Override
	public void saveEntity(BasePoEntity obj) throws Exception {
		GenericDao<? extends BasePoEntity> impl = impl(obj.getClass());
		Method saveMethod = Stream.of(impl.getClass().getMethods()).filter(m -> m.getName().equals("saveEntity")).findFirst().get();
		saveMethod.invoke(impl, obj);
	}

	@Override
	public <T extends BasePoEntity> int updateByCriteria(Class<T> entityClass, Map<String, Object> contains, InnerCriteria cri) throws Exception {
		return impl(entityClass).updateByCriteria(contains, cri);
	}

	@Override
	public <T extends BasePoEntity> int deleteByCriteria(Class<T> entityClass, InnerCriteria delCri) throws Exception {
		return impl(entityClass).deleteByCriteria(delCri);
	}

	@Override
	public <T extends BasePoEntity> int countByCriteria(Class<T> entityClass, InnerCriteria criteria) throws Exception {
		return impl(entityClass).countByCriteria(criteria);
	}

	@Override
	public <T extends BasePoEntity> List<T> query(Class<T> entityClass, InnerCriteria criteria, PageCount page) throws Exception {
		return impl(entityClass).query(criteria, page);
	}

	@SuppressWarnings("unchecked")
	private <T extends BasePoEntity> GenericDao<T> impl(Class<T> entityClass) throws Exception {
		return (GenericDao<T>) BaseGeneric.beanOf(GenericDao.class, entityClass);
	}
}
